package com.googlecode.kipler.container.dl.operational;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.googlecode.kipler.container.dl.ABox;
import com.googlecode.kipler.container.dl.Individual;
import com.googlecode.kipler.container.dl.SHOIQABox;
import com.googlecode.kipler.satisfiability.blocking.abox.SHOIQDoubleBlocking;
import com.googlecode.kipler.syntax.Role;
import com.googlecode.kipler.syntax.concept.Concept;
import com.googlecode.kipler.syntax.formula.ObjectRoleAssertion;


/**
 * 
 * @author İnanç Seylan
 *
 */
public class TypedSafeNeighborFilter implements RelatedIndividualWithTypeFilter {

	private ABox aBox;

	private Role role;

	private Individual individual;

	private Concept concept;

	public ABox getABox() {
		return aBox;
	}

	public void setABox(ABox box) {
		aBox = box;
	}

	public Concept getConcept() {
		return concept;
	}

	public void setConcept(Concept concept) {
		this.concept = concept;
	}

	public Individual getIndividual() {
		return individual;
	}

	public void setIndividual(Individual owner) {
		this.individual = owner;
	}

	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public Set<Individual> filter() {
		Set<Individual> result = new HashSet<Individual>();
		Iterator<ObjectRoleAssertion> raIter = getABox().neighborIterator(
				getRole(), getIndividual());
		while (raIter.hasNext()) {
			ObjectRoleAssertion ra = raIter.next().normalize(
					getIndividual().getName());
			Individual filler = getABox().getIndividual(ra.getFiller());
			if (filler.contains(getConcept())
					&& isSafeNeighbor(getIndividual(), filler)) {
				result.add(filler);
			}
		}
		return result;
	}

	public boolean contains() {
		boolean found = false;
		Iterator<ObjectRoleAssertion> raIter = getABox().neighborIterator(
				getRole(), getIndividual());
		while (raIter.hasNext() && !found) {
			ObjectRoleAssertion ra = raIter.next().normalize(
					getIndividual().getName());
			Individual filler = getABox().getIndividual(ra.getFiller());
			if (filler.contains(getConcept())
					&& isSafeNeighbor(getIndividual(), filler)) {
				found = true;
			}
		}
		return found;
	}

	private boolean isSafeNeighbor(Individual x, Individual y) {
		SHOIQABox shoiqABox = (SHOIQABox) getABox();
		return shoiqABox.isBlockable(x)
				|| (shoiqABox.isNominal(x) && !new SHOIQDoubleBlocking()
						.isBlocked(shoiqABox, y.getName()));
	}

}
